package org.xtense.model.actions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Element;
import org.dom4j.Node;
import org.xtense.model.CAttribute;
import org.xtense.model.CElement;

public class ResultCache {
	
	// for clean the cache , go though the list to avoid
	// ConcurrentModificationException.
	private static HashMap<Integer, List<Node>> all = new HashMap<Integer, List<Node>>();
	
	private static HashMap<Node, int[]> cacheDocPre = new HashMap<Node, int[]>();

	// for query
	public static void cacheElement(Node us, int documentId, CElement ce) {
		cacheDocPre.put(us, new int[] { documentId, ce.getElementPre(),
				ce.getParentPre() });
		List<Node> l = all.get(documentId);
		if (l == null) {
			l = new ArrayList<Node>();
			all.put(documentId, l);
		}
		l.add(us);
	}
	
	public static void cacheAttribute(Node us, int documentId, CAttribute ca) {
		cacheDocPre.put(us, new int[] { documentId, ca.getElementPre() });
		List<Node> l = all.get(documentId);
		if (l == null) {
			l = new ArrayList<Node>();
			all.put(documentId, l);
		}
		l.add(us);
	}
	
	// for update
	public static void removeCache(Node us) {
		cacheDocPre.remove(us);
	}

	public static int getDocumentIdFromNode(Node us) {
		if (cacheDocPre.containsKey(us)) {
			return cacheDocPre.get(us)[0];
		} else {
			return -1;
		}
	}
	
	public static int getElementPreFromNode(Node us) {
		if (cacheDocPre.containsKey(us)) {
			return cacheDocPre.get(us)[1];
		} else {
			return -1;
		}
	}

	public static int getParentPreFromNode(Node us) {
		if (cacheDocPre.containsKey(us)) {
			if (us instanceof Element) {
				return cacheDocPre.get(us)[2];
			} else {
				return -1;
			}
		} else {
			return -1;
		}
	}
	
	public static void updateForAdd(int docID, int elementPre, int size) {
		List<Node> list = all.get(docID);
		for (Node n : list) {
			int[] values = cacheDocPre.get(n);
			if (values[1] > elementPre) {
				values[1] = values[1] + size;
			}
			if (n instanceof Element) {
				
				if (values[2] > elementPre) {
					values[2] = values[2] + size;
				}
			}
		}

	}
	
	public static void updateForDel(int docID, int elementPre, int size) {
		List<Node> list = all.get(docID);
		for (Node n : list) {
			int[] values = cacheDocPre.get(n);
			if (values[1] > elementPre) {
				values[1] = values[1] - size;
			}
			if (n instanceof Element) {

				if (values[2] > elementPre) {
					values[2] = values[2] - size;
				}
			}
		}

	}
	
	private static HashMap<Node, String> cachePath = new HashMap<Node, String>();
	public static void cachePath(Node us,String path) {
		cachePath.put(us, path);
	}
	public static void removePath(Node us) {
		cachePath.remove(us);
	}
	public static String getPathFromNode(Node us) {
		return cachePath.get(us);
	}
	
	public static void clean(int docID) {
		List<Node> l = all.get(docID);
		for (Node n : l) {
			if (n instanceof Element) {
				cacheDocPre.remove(n);
				cachePath.remove(n);
			} else if (n instanceof Attribute) {
				cacheDocPre.remove(n);
			}
		}
		all.remove(docID);
	}

}
